package luminus.origin.commands.teleport

import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import taboolib.common.platform.command.*
import taboolib.platform.util.sendLang
import kotlin.math.round

@CommandHeader(name = "tp", permission = "luminus.tp", aliases = ["teleport"])
object Teleport {

    @CommandBody
    val main = mainCommand {
        execute<Player> { sender, _, _ ->
            sender.sendLang("teleport-tp-usage")
        }

        // tp here <player>
        literal("here", permission = "luminus.tp.here") {
            dynamic("player") {
                suggest { Bukkit.getOnlinePlayers().map { it.name } }
                execute<Player> { sender, _, argument ->
                    val target = Bukkit.getPlayer(argument) ?: run {
                        sender.sendLang("teleport-tp-player-not-found", argument)
                        return@execute
                    }
                    target.teleport(sender)
                    sender.sendLang("teleport-tp-here-success", target.name)
                }
            }
        }

        // tp all (crazy bad performance)
        literal("all", permission = "luminus.tp.all") {
            execute<Player> { sender, _, _ ->
                Bukkit.getOnlinePlayers().forEach { player ->
                    if (player != sender) {
                        player.teleport(sender)
                    }
                }
                sender.sendLang("teleport-tp-all-success")
            }
        }

        // tp <player>
        dynamic("player") {
            suggest { Bukkit.getOnlinePlayers().map { it.name } }
            execute<Player> { sender, _, argument ->
                val target = Bukkit.getPlayer(argument) ?: run {
                    sender.sendLang("teleport-tp-player-not-found", argument)
                    return@execute
                }
                sender.teleport(target)
                sender.sendLang("teleport-tp-success-to-player", target.name)
            }
        }

        // tp <player1> <player2>
        dynamic("player1") {
            suggest { Bukkit.getOnlinePlayers().map { it.name } }
            dynamic("player2") {
                suggest { Bukkit.getOnlinePlayers().map { it.name } }
                execute<CommandSender> { sender, context, _ ->
                    val player1 = Bukkit.getPlayer(context["player1"]) ?: run {
                        sender.sendLang("teleport-tp-player-not-found", context["player1"])
                        return@execute
                    }
                    val player2 = Bukkit.getPlayer(context["player2"]) ?: run {
                        sender.sendLang("teleport-tp-player-not-found", context["player2"])
                        return@execute
                    }
                    player1.teleport(player2)
                    sender.sendLang("teleport-tp-player-to-player", player1.name, player2.name)
                }
            }
        }

        // tp <x> <y> <z>
        dynamic("x") {
            dynamic("y") {
                dynamic("z") {

                    execute<Player> { sender, context, _ ->
                        val x = context.int("x").toDouble()
                        val y = context.int("y").toDouble()
                        val z = context.int("z").toDouble()
                        val loc = Location(sender.world, x, y, z, sender.location.yaw, sender.location.pitch)
                        sender.teleport(loc)
                        sender.sendLang(
                            "tp-success-to-coords",
                            round(x * 10) / 10,
                            round(y * 10) / 10,
                            round(z * 10) / 10
                        )
                    }
                }
            }
        }

        // tp <player> <x> <y> <z>
        dynamic("target") {
            suggest { Bukkit.getOnlinePlayers().map { it.name } }
            dynamic("x") {

                dynamic("y") {

                    dynamic("z") {

                        execute<CommandSender> { sender, context, _ ->
                            val target = Bukkit.getPlayer(context["target"]) ?: run {
                                sender.sendLang("teleport-tp-player-not-found", context["target"])
                                return@execute
                            }
                            val x = context.int("x").toDouble()
                            val y = context.int("y").toDouble()
                            val z = context.int("z").toDouble()
                            val loc = Location(target.world, x, y, z, target.location.yaw, target.location.pitch)
                            target.teleport(loc)
                            sender.sendLang(
                                "tp-player-to-coords",
                                target.name,
                                round(x * 10) / 10,
                                round(y * 10) / 10,
                                round(z * 10) / 10
                            )
                        }
                    }
                }
            }
        }


    }
}        